#include "commtick.hpp"
#include "sdk_config.h"
#include "hc32_ddl.h"
///>滴答函数，在中断中执行
using namespace device;
#define COMMTICK_IRQ_NUM		0

typedef struct
{
	commtick::CommTickDelagate tCallBack;
	uint32_t uiTickMs;
	uint32_t uiTickCount;
}RegisterQueueTPDF;

RegisterQueueTPDF mRegisterQueue[COMMTICK_MAX_SURPPORT];
uint32_t mRegisterQueueCount = 0;
bool mEnabled = false;

extern "C"
{
	void IRQ000_Handler(void)
	{
		uint32_t i;
		for(i = 0; i < mRegisterQueueCount; i++)
		{
			if(mRegisterQueue[i].tCallBack == 0)
			{
				continue;
			}
			mRegisterQueue[i].uiTickCount++;
			if(mRegisterQueue[i].uiTickCount < mRegisterQueue[i].uiTickMs)
			{
				continue;
			}
			if(!mRegisterQueue[i].tCallBack())  
			{
				mRegisterQueue[i].tCallBack = 0;///> 当执行失败就不执行
			}
			mRegisterQueue[i].uiTickCount = 0;
		}
	}
}

static bool Timer2Enable(void)
{
	uint32_t clk;
	uint8_t div;
	
	clk = ClockFreqGet(CLOCK_TYPE_APB1);	
	M4_TMR01->BCONR &= 0xFFFF0000ul;
	while(M4_TMR01->BCONR & 0x0000fffful);
	M4_TMR01->BCONR_f.SYNCLKA = 0;
	for(div = 0; div < 11; div++)
	{
		if((clk >> div) < (65535 * 1000))
		{
			break;
		}
	}
	M4_TMR01->BCONR_f.CKDIVA = div;
	M4_TMR01->CMPAR = ((clk >> div) / 1000) - 1;
	M4_TMR01->BCONR_f.SYNSA = 0;
	M4_TMR01->BCONR_f.INTENA = 1;
	
	*(uint32_t *)(((uint32_t)&M4_INTC->SEL0) + (4 * COMMTICK_IRQ_NUM)) = INT_TMR01_GCMA;
	NVIC_ClearPendingIRQ((IRQn)COMMTICK_IRQ_NUM);
	NVIC_SetPriority((IRQn)COMMTICK_IRQ_NUM, 4);
	NVIC_EnableIRQ((IRQn)COMMTICK_IRQ_NUM);

	M4_TMR01->BCONR_f.CSTA = 1;
	return(true);
}

bool commtick::RegisteTick(CommTickDelagate tCallBack, uint32_t uiTickMs)
{
	uint32_t i;
	for(i = 0; i < mRegisterQueueCount; i++)
	{
		if(mRegisterQueue[i].tCallBack == 0)
		{
			mRegisterQueue[i].uiTickMs = uiTickMs;
			mRegisterQueue[i].uiTickCount = 0;
			mRegisterQueue[i].tCallBack = tCallBack;
			return(true);
		}
	}
	if(mRegisterQueueCount == COMMTICK_MAX_SURPPORT)
	{
		return(false);
	}
	mRegisterQueue[mRegisterQueueCount].tCallBack = tCallBack;
	mRegisterQueue[mRegisterQueueCount].uiTickMs = uiTickMs;
	mRegisterQueue[mRegisterQueueCount].uiTickCount = 0;
	mRegisterQueueCount++;
	
	if(!mEnabled)
	{
		if(!Timer2Enable())
		{
			return(false);
		}
		mEnabled = true;
	}
	return(true);
}
